/*
  1. 打开组件时
    请求权限列表数据, 根据列表数据渲染表格

  2. 分配权限
    打开分配权限框时
      请求所有权限信息, 需要一个树状数据结构
        打开页面时, 就可以把所有权限请求回来
      拿到当前角色拥有的权限信息
        把里面的 id 拿出来, 用于把一些权限选中

  3. 删除某一条权限
    点击某一个权限 tag 标签的 删除按钮时 删除
    拿到当前这一条数据的 roleId (角色 id)
    拿到被点击的这个按钮的 rightId (权限 id)
*/

export default {
  name: 'Rules',
  data () {
    return {
      // 角色列表
      rolesList: [],
      // 添加角色 dialog 是否显示
      addRolesDialog: false,
      // 添加角色的信息
      addRolesInfo: {},
      // 添加角色表单验证
      addRolesRules: {
        roleName: [
          { required: true, message: '请填写角色名称', trigger: 'change' }
        ],
        roleDesc: [
          { required: true, message: '请填写角色名称', trigger: 'change' }
        ]
      },
      // 编辑角色信息对话框
      editRolesDialog: false,
      // 编辑角色信息
      editRolesInfo: {
        roleName: '',
        roleDesc: '',
        id: 0
      },
      editRightsDialog: false,
      // 权限列表 树状
      rightsList: [],
      // 权限列表中选中的数组
      checkedRightsList: [],
      // 权限树的信息
      rightsTreeInfo: {
        // 表示数据中哪一个属性名是显示的文本
        label: 'authName',
        // 表示数据中哪一个属性名是二级菜单选项
        children: 'children'
      },
      // 当前角色id
      roleId: 0
    }
  },
  created () {
    // 请求角色列表
    this.getRolesList()
    // 请求所有权限列表  树状
    this.getRightsList()
  },
  methods: {
    // 请求权限列表
    async getRolesList () {
      // 请求列表
      const { data } = await this.$get('roles')
      // 给 data 内的 rolesList 进行赋值
      this.rolesList = data
    },
    // 关闭添加角色对话框
    closeAddRolesDialog () {
      this.$refs.addRoles.resetFields()

      // 重置对象
      this.addRolesInfo = {}
    },
    // 确认添加角色
    addRolesHandler () {
      // 发送请求进行添加角色操作
      this.$refs.addRoles.validate(async valid => {
        if (!valid) {
          this.$message({
            type: 'error',
            message: '请按规则完整填写表单'
          })
          return
        }

        // 代码来到这里, 说明表单验证通过
        const { meta } = await this.$post('roles', { roleName: this.addRolesInfo.roleName, roleDesc: this.addRolesInfo.roleDesc })
        if (meta.status === 201) {
          this.$message({
            type: 'success',
            message: '创建角色成功'
          })
          this.addRolesDialog = false
          // 重新请求角色列表
          this.getRolesList()
        }
      })
    },
    // 删除角色
    deleteRolesHandler (id) {
      // 利用 confirm 来实现删除消息
      this.$confirm('您确定要删除该角色吗?', '删除角色', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(async () => {
        const { meta } = await this.$delete('roles/' + id)
        if (meta.status === 200) {
          this.$message({
            type: 'success',
            message: '删除成功!'
          })
          // 重新请求列表
          this.getRolesList()
        }
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    // 展示编辑角色信息对话框
    showEditInfoDialog (val) {
      // 接受一些参数
      // 把信息存储起来
      this.editRolesInfo.id = val.id
      this.editRolesInfo.roleName = val.roleName
      this.editRolesInfo.roleDesc = val.roleDesc
      // 展开对话框
      this.editRolesDialog = true
    },
    // 确认编辑角色信息
    async editRolesInfoHandler () {
      // 直接发送请求进行修改
      const { meta } = await this.$put('roles/' + this.editRolesInfo.id, { roleName: this.editRolesInfo.roleName, roleDesc: this.editRolesInfo.roleDesc })
      if (meta.status === 200) {
        this.$message({
          type: 'success',
          message: '编辑用户信息成功'
        })
      }
      this.getRolesList()
      this.editRolesDialog = false
    },
    // 请求所有权限列表
    async getRightsList () {
      const { data } = await this.$get('rights/tree')
      // 把数据赋值
      this.rightsList = data
    },
    // 展开分配权限对话框
    showEditRightsHandler (val, id) {
      // 给 this.roleId 赋值
      this.roleId = id
      // 拿到 val.children 所有项的 id
      // 以及 所有 children 内的 children 的 id
      // 注意: 实际应该获取所有三级权限的 id
      val.forEach(item => {
        if (!item.children) return

        // 遍历二级权限
        item.children.forEach(t => {
          if (!t.children) return

          // 遍历三级权限
          t.children.forEach(t2 => {
            // 把三级权限的 id 填充到 checkedRightsList 内
            this.checkedRightsList.push(t2.id)
          })
        })
      })

      // 展开对话框
      this.editRightsDialog = true
    },
    // 关闭权限分配对话框
    closeRightsDialog () {
      // 让 checkedRightsList 数组归零
      this.checkedRightsList = []
    },
    // 确认编辑权限
    /*
      参数:
        rids: 101, 102, 103, 104

      注意:
        服务器是完全替换式的赋值
          例子: 本身 101, 102
            第二次设置 103
            变成只有 103
        服务器不会自动识别父级权限
          例子:
            父子权限列表
              父亲: 101
              孩子: 102, 103
            设置时
              如果只传递 102, 103
              只设置 102, 103
              不设置 101
    */
    async editRightsInfoHandler () {
      // 拿到 tree 组件中的需要选中项
      // 拿到 tree 组件中所有 选中 和 半选中 的 id
      // 拿到组件中所有选中项的 id
      const checkedIds = this.$refs.rightsTree.getCheckedKeys()
      // 拿到 tree 组件中所有半选中项的 id
      const halfCheckedIds = this.$refs.rightsTree.getHalfCheckedKeys()

      // 把这两个数组合并在一起发给后端
      // 准备参数
      const rids = [...checkedIds, ...halfCheckedIds] + ''
      // 如果数组内全部都是基本数据类型
      // 会在进行字符串拼接的时候, 会自动转换成 join(',') 的形式
      const { meta } = await this.$post(`roles/${this.roleId}/rights`, { rids })
      if (meta.status === 200) {
        this.$message({
          type: 'success',
          message: '角色授权成功'
        })
      }
      this.getRolesList()
      this.editRightsDialog = false
    },
    // 删除角色单一权限信息
    async deleteRightsHandler (roleId, rightId) {
      // 拿到 roleId 和 rightId
      // 发送请求, 进行删除操作
      const { meta } = await this.$delete(`roles/${roleId}/rights/${rightId}`)
      if (meta.status === 200) {
        this.$message({
          type: 'success',
          message: '取消用户权限成功'
        })
      }
      this.getRolesList()
      // 为了更好的视觉效果, 不重新请求角色列表渲染页面
      // 直接从原始数组中删除某一条权限
      // 1. 直接遍历 this.rolesList 找到需要的数据去删除
      let rights = []
      for (let i = 0; i < this.rolesList.length; i++) {
        if (this.rolesList[i].id === roleId) {
          rights = this.rolesList[i].children
        }
      }
      // 2. 开始遍历 rights, 开始进行后续操作
      for (let i = 0; i < rights.length; i++) {
        // rights 是每一个一级权限
        const first = rights[i]
        // 判断 first.id === rightId, 说明找到要删除的那一个了
        if (first.id === rightId) {
          // 从 rights 内删除索引为 i 的这一条
          rights.splice(i, 1)
          break
        }
        // 代码执行到这里, 说明这一条不是我要删除的那一条
        // 根据 first.children 去遍历二级权限
        for (let j = 0; j < first.children.length; j++) {
          const second = first.children[j]
          // 判断 second.id === rightId, 说明找到要删除的那一个了
          if (second.id === rightId) {
            first.children.splice(j, 1)
            break
          }
          // 代码执行到这里, 说明这一条不是我要删除的那一条
          // 根据 second.children 去遍历三级权限
          for (let j = 0; j < second.children.length; j++) {
            const third = second.children[j]
            // 判断 third.id === rightId, 说明找到要删除的那一个了
            if (third.id === rightId) {
              second.children.splice(j, 1)
              break
            }
          }
        }
      }
    }
  }
}
